rockchip/rk3399: set ddr clock source back to dpll when ddr resume
authorLin Huang <hl@rock-chips.com>
Wed, 17 May 2017 08:14:37 +0000 (16:14 +0800)
committerCaesar Wang <wxt@rock-chips.com>
Tue, 29 Aug 2017 03:53:29 +0000 (11:53 +0800)
when logic power rail shutdown, CRU register will back to reset
value, ddr use abpll as clock source when do suspend, we need to save
and dpll value in pmusram, then set back these ddr clock back to dpll
when dddr resume.

Change-Id: I95dc0173649e8515859cfa46b40a606e0cc2fe3f
Signed-off-by: Lin Huang <hl@rock-chips.com>
plat/rockchip/common/pmusram/pmu_sram_cpus_on.S
plat/rockchip/rk3399/drivers/dram/suspend.c
plat/rockchip/rk3399/drivers/dram/suspend.h
plat/rockchip/rk3399/drivers/pmu/pmu.c
plat/rockchip/rk3399/drivers/soc/soc.c
plat/rockchip/rk3399/drivers/soc/soc.h

index 22bdffcae1f0ea38873020e95a5f49804828f48e..5a1854b4218668b6222e3b2087841450033de97e 100644 (file)
@@ -45,7 +45,7 @@ sys_wakeup:
 ddr_resume:
        ldr     x2, =__bl31_sram_stack_end
        mov     sp, x2
-       bl      dmc_restore
+       bl      dmc_resume
 #endif
        bl      sram_restore
 sys_resume:
index 68677449822548a3edab838fc4ef707b515db905..89f0cd38882a1e78ce9f88efc4325c5ab546c7ec 100644 (file)
@@ -43,6 +43,9 @@
 
 #define SYS_COUNTER_FREQ_IN_MHZ                (SYS_COUNTER_FREQ_IN_TICKS / 1000000)
 
+__pmusramdata uint32_t dpll_data[PLL_CON_COUNT];
+__pmusramdata uint32_t cru_clksel_con6;
+
 /*
  * Copy @num registers from @src to @dst
  */
@@ -636,24 +639,45 @@ static __pmusramfunc int pctl_start(uint32_t channel_mask,
        return 0;
 }
 
-void dmc_save(void)
+__pmusramfunc static void pmusram_restore_pll(int pll_id, uint32_t *src)
+{
+       mmio_write_32((CRU_BASE + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
+
+       mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 0), src[0] | REG_SOC_WMSK);
+       mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 1), src[1] | REG_SOC_WMSK);
+       mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 2), src[2]);
+       mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 4), src[4] | REG_SOC_WMSK);
+       mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 5), src[5] | REG_SOC_WMSK);
+
+       mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), src[3] | REG_SOC_WMSK);
+
+       while ((mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 2)) &
+               (1 << 31)) == 0x0)
+               ;
+}
+
+void dmc_suspend(void)
 {
        struct rk3399_sdram_params *sdram_params = &sdram_config;
        struct rk3399_ddr_publ_regs *phy_regs;
        uint32_t *params_ctl;
        uint32_t *params_pi;
        uint32_t refdiv, postdiv2, postdiv1, fbdiv;
-       uint32_t tmp, ch, byte, i;
+       uint32_t ch, byte, i;
 
        phy_regs = &sdram_params->phy_regs;
        params_ctl = sdram_params->pctl_regs.denali_ctl;
        params_pi = sdram_params->pi_regs.denali_pi;
 
-       fbdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 0)) & 0xfff;
-       tmp = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1));
-       postdiv2 = POSTDIV2_DEC(tmp);
-       postdiv1 = POSTDIV1_DEC(tmp);
-       refdiv = REFDIV_DEC(tmp);
+       /* save dpll register and ddr clock register value to pmusram */
+       cru_clksel_con6 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON6);
+       for (i = 0; i < PLL_CON_COUNT; i++)
+               dpll_data[i] = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, i));
+
+       fbdiv = dpll_data[0] & 0xfff;
+       postdiv2 = POSTDIV2_DEC(dpll_data[1]);
+       postdiv1 = POSTDIV1_DEC(dpll_data[1]);
+       refdiv = REFDIV_DEC(dpll_data[1]);
 
        sdram_params->ddr_freq = ((fbdiv * 24) /
                                (refdiv * postdiv1 * postdiv2)) * MHz;
@@ -697,12 +721,20 @@ void dmc_save(void)
        phy_regs->phy896[0] &= ~(0x3 << 8);
 }
 
-__pmusramfunc void dmc_restore(void)
+__pmusramfunc void dmc_resume(void)
 {
        struct rk3399_sdram_params *sdram_params = &sdram_config;
        uint32_t channel_mask = 0;
        uint32_t channel;
 
+       /*
+        * we switch ddr clock to abpll when suspend,
+        * we set back to dpll here
+        */
+       mmio_write_32(CRU_BASE + CRU_CLKSEL_CON6,
+                       cru_clksel_con6 | REG_SOC_WMSK);
+       pmusram_restore_pll(DPLL_ID, dpll_data);
+
        configure_sgrf();
 
 retry:
index 77f9c317b13858956d94a6cd24dba3651af9fc75..a8a864108941dc2c7609aac968857368c3f19c22 100644 (file)
@@ -19,7 +19,7 @@
 #define PI_WDQ_LEVELING                (1 << 4)
 #define PI_FULL_TRAINING       (0xff)
 
-void dmc_save(void);
-__pmusramfunc void dmc_restore(void);
+void dmc_suspend(void);
+__pmusramfunc void dmc_resume(void);
 
 #endif /* __DRAM_H__ */
index 635dda6ad8bb480275887bc34caec4f345740d96..d97b0463b171b5d082ded73c32ba171a110a282b 100644 (file)
@@ -1138,7 +1138,7 @@ int rockchip_soc_sys_pwr_dm_suspend(void)
        uint32_t status = 0;
 
        ddr_prepare_for_sys_suspend();
-       dmc_save();
+       dmc_suspend();
        pmu_scu_b_pwrdn();
 
        pmu_power_domains_suspend();
@@ -1269,8 +1269,6 @@ int rockchip_soc_sys_pwr_dm_resume(void)
        pmu_scu_b_pwrup();
        pmu_power_domains_resume();
 
-       restore_dpll();
-       sram_func_set_ddrctl_pll(DPLL_ID);
        restore_abpll();
 
        clr_hw_idle(BIT(PMU_CLR_CENTER1) |
index 993b80ad4833428358e6190bad0bd94dc8dc434a..175d5427564954e4e24ac98234824f35f5db42dc 100644 (file)
@@ -171,11 +171,6 @@ void restore_abpll(void)
        restore_pll(ABPLL_ID, slp_data.plls_con[ABPLL_ID]);
 }
 
-void restore_dpll(void)
-{
-       restore_pll(DPLL_ID, slp_data.plls_con[DPLL_ID]);
-}
-
 void clk_gate_con_save(void)
 {
        uint32_t i = 0;
index 8d1fd13ff9eb1945d02b7cdab58402d3003daf74..9680beab5b871025bfa6270aec9ab7dbebb49127 100644 (file)
@@ -196,6 +196,7 @@ struct deepsleep_data_s {
 #define GRF_SOC_CON_BASE       0xe200
 #define GRF_SOC_CON(n)         (GRF_SOC_CON_BASE + (n) * 4)
 
+#define CRU_CLKSEL_CON6                0x0118
 #define PMUCRU_CLKSEL_CON0     0x0080
 #define PMUCRU_CLKGATE_CON2    0x0108
 #define PMUCRU_SOFTRST_CON0    0x0110
@@ -231,7 +232,6 @@ void enable_dvfs_plls(void);
 void enable_nodvfs_plls(void);
 void prepare_abpll_for_ddrctrl(void);
 void restore_abpll(void);
-void restore_dpll(void);
 void clk_gate_con_save(void);
 void clk_gate_con_disable(void);
 void clk_gate_con_restore(void);